{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 量子神经网络在自然语言处理中的应用\n",
    "\n",
    "[![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/mindquantum/zh_cn/case_library/mindspore_qnn_for_nlp.ipynb)&emsp;[![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/mindquantum/zh_cn/case_library/mindspore_qnn_for_nlp.py)&emsp;[![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/docs/mindquantum/docs/source_zh_cn/case_library/qnn_for_nlp.ipynb)\n",
    "\n",
    "## 概述\n",
    "\n",
    "在自然语言处理过程中，词嵌入（Word embedding）是其中的重要步骤，它是一个将高维度空间的词向量嵌入到一个维数更低的连续向量空间的过程。当给予神经网络的语料信息不断增加时，网络的训练过程将越来越困难。利用量子力学的态叠加和纠缠等特性，我们可以利用量子神经网络来处理这些经典语料信息，加入其训练过程，并提高收敛精度。下面，我们将简单地搭建一个量子经典混合神经网络来完成一个词嵌入任务。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.mirrors.ustc.edu.cn/simple\n",
      "Collecting mindquantum\n",
      "  Downloading https://mirrors.ustc.edu.cn/pypi/packages/7f/9a/6d869a5e632b8a80f92ff9d4bd6c3dcae9e319c9fb0384b3bf9c81500cf2/mindquantum-0.9.11-cp39-cp39-manylinux1_x86_64.whl (81.4 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m81.4/81.4 MB\u001b[0m \u001b[31m124.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: scipy>=1.5.3 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindquantum) (1.13.1)\n",
      "Requirement already satisfied: matplotlib>=3.4.3 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from mindquantum) (3.9.2)\n",
      "Collecting rich==10.9.0 (from mindquantum)\n",
      "  Downloading https://mirrors.ustc.edu.cn/pypi/packages/e9/c4/ea9a6e34dd5c4c3049b0a86c49feb7f38c9f5e901ffb6eeb832e89dfa540/rich-10.9.0-py3-none-any.whl (211 kB)\n",
      "Requirement already satisfied: colorama<0.5.0,>=0.4.0 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from rich==10.9.0->mindquantum) (0.4.6)\n",
      "Collecting commonmark<0.10.0,>=0.9.0 (from rich==10.9.0->mindquantum)\n",
      "  Downloading https://mirrors.ustc.edu.cn/pypi/packages/b1/92/dfd892312d822f36c55366118b95d914e5f16de11044a27cf10a7d71bbbf/commonmark-0.9.1-py2.py3-none-any.whl (51 kB)\n",
      "Requirement already satisfied: pygments<3.0.0,>=2.6.0 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from rich==10.9.0->mindquantum) (2.18.0)\n",
      "Requirement already satisfied: contourpy>=1.0.1 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (1.2.1)\n",
      "Requirement already satisfied: cycler>=0.10 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (0.12.1)\n",
      "Requirement already satisfied: fonttools>=4.22.0 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (4.53.1)\n",
      "Requirement already satisfied: kiwisolver>=1.3.1 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (1.4.5)\n",
      "Requirement already satisfied: numpy>=1.23 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (1.26.4)\n",
      "Requirement already satisfied: packaging>=20.0 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (24.1)\n",
      "Requirement already satisfied: pillow>=8 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (10.4.0)\n",
      "Requirement already satisfied: pyparsing>=2.3.1 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (3.1.2)\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (2.9.0.post0)\n",
      "Requirement already satisfied: importlib-resources>=3.2.0 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from matplotlib>=3.4.3->mindquantum) (6.4.2)\n",
      "Requirement already satisfied: zipp>=3.1.0 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from importlib-resources>=3.2.0->matplotlib>=3.4.3->mindquantum) (3.20.0)\n",
      "Requirement already satisfied: six>=1.5 in /home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages (from python-dateutil>=2.7->matplotlib>=3.4.3->mindquantum) (1.16.0)\n",
      "Installing collected packages: commonmark, rich, mindquantum\n",
      "  Attempting uninstall: rich\n",
      "    Found existing installation: rich 13.7.1\n",
      "    Uninstalling rich-13.7.1:\n",
      "      Successfully uninstalled rich-13.7.1\n",
      "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
      "typer 0.12.3 requires rich>=10.11.0, but you have rich 10.9.0 which is incompatible.\u001b[0m\u001b[31m\n",
      "\u001b[0mSuccessfully installed commonmark-0.9.1 mindquantum-0.9.11 rich-10.9.0\n"
     ]
    }
   ],
   "source": [
    "# 安装 mindquantum\n",
    "!pip install mindquantum -i https://pypi.mirrors.ustc.edu.cn/simple"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "导入本教程所依赖模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/nginx/miniconda/envs/jupyter/lib/python3.9/site-packages/mindquantum/simulator/__init__.py:17: UserWarning: Disable mqvector gpu backend due to: Malloc GPU memory failed: cudaErrorInsufficientDriver, CUDA driver version is insufficient for CUDA runtime version\n",
      "  from .available_simulator import SUPPORTED_SIMULATOR\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import time\n",
    "import mindspore as ms\n",
    "import mindspore.ops as ops\n",
    "import mindspore.dataset as ds\n",
    "from mindspore import nn\n",
    "from mindquantum.framework import MQLayer\n",
    "from mindquantum.core.gates import RX, RY, X, H\n",
    "from mindquantum.core.circuit import Circuit, UN\n",
    "from mindquantum.core.operators import Hamiltonian, QubitOperator"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "本教程实现的是一个[CBOW模型](https://blog.csdn.net/u010665216/article/details/78724856)，即利用某个词所处的环境来预测该词。例如对于“I love natural language processing”这句话，我们可以将其切分为5个词，\\[\"I\", \"love\", \"natural\", \"language\", \"processing”\\]，在所选窗口为2时，我们要处理的问题是利用\\[\"I\", \"love\", \"language\", \"processing\"\\]来预测出目标词汇\"natural\"。这里我们以窗口为2为例，搭建如下的量子神经网络，来完成词嵌入任务。\n",
    "\n",
    "![quantum word embedding](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindquantum/docs/source_zh_cn/images/qcbow.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这里，编码线路会将\"I\"、\"love\"、\"language\"和\"processing\"的编码信息编码到量子线路中，待训练的量子线路由四个Ansatz线路构成，最后我们在量子线路末端对量子比特做$\\text{Z}$基矢上的测量，具体所需测量的比特的个数由所需嵌入空间的维数确定。\n",
    "\n",
    "## 数据预处理\n",
    "\n",
    "我们对所需要处理的语句进行处理，生成关于该句子的词典，并根据窗口大小来生成样本点。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def GenerateWordDictAndSample(corpus, window=2):\n",
    "    all_words = corpus.split()\n",
    "    word_set = list(set(all_words))\n",
    "    word_set.sort()\n",
    "    word_dict = {w: i for i, w in enumerate(word_set)}\n",
    "    sampling = []\n",
    "    for index, _ in enumerate(all_words[window:-window]):\n",
    "        around = []\n",
    "        for i in range(index, index + 2*window + 1):\n",
    "            if i != index + window:\n",
    "                around.append(all_words[i])\n",
    "        sampling.append([around, all_words[index + window]])\n",
    "    return word_dict, sampling"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'I': 0, 'language': 1, 'love': 2, 'natural': 3, 'processing': 4}\n",
      "word dict size:  5\n",
      "samples:  [[['I', 'love', 'language', 'processing'], 'natural']]\n",
      "number of samples:  1\n"
     ]
    }
   ],
   "source": [
    "word_dict, sample = GenerateWordDictAndSample(\"I love natural language processing\")\n",
    "print(word_dict)\n",
    "print('word dict size: ', len(word_dict))\n",
    "print('samples: ', sample)\n",
    "print('number of samples: ', len(sample))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据如上信息，我们得到该句子的词典大小为5，能够产生一个样本点。\n",
    "\n",
    "## 编码线路\n",
    "\n",
    "为了简单起见，我们使用的编码线路由$\\text{RX}$旋转门构成，结构如下。\n",
    "\n",
    "![encoder circuit](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindquantum/docs/source_zh_cn/images/encoder.png)\n",
    "\n",
    "我们对每个量子门都作用一个$\\text{RX}$旋转门。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def GenerateEncoderCircuit(n_qubits, prefix=''):\n",
    "    if prefix and prefix[-1] != '_':\n",
    "        prefix += '_'\n",
    "    circ = Circuit()\n",
    "    for i in range(n_qubits):\n",
    "        circ += RX(prefix + str(i)).on(i)\n",
    "    return circ.as_encoder()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"156.8\" height=\"200.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"156.8\" height=\"200.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><line x1=\"48.8\" x2=\"136.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"136.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"136.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"20.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"92.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >e_0 </text><rect x=\"72.8\" y=\"80.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"92.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >e_1 </text><rect x=\"72.8\" y=\"140.0\" width=\"40.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"92.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RX </text><text x=\"92.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >e_2 </text></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f91baf9d130>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "GenerateEncoderCircuit(3, prefix='e').svg()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们通常用$\\left|0\\right>$和$\\left|1\\right>$来标记二能级量子比特的两个状态，由态叠加原理，量子比特还可以处于这两个状态的叠加态：\n",
    "\n",
    "$$\\left|\\psi\\right>=\\alpha\\left|0\\right>+\\beta\\left|1\\right>$$\n",
    "\n",
    "对于$n$比特的量子态，其将处于$2^n$维的希尔伯特空间中。对于上面由5个词构成的词典，我们只需要$\\lceil \\log_2 5 \\rceil=3$个量子比特即可完成编码，这也体现出量子计算的优越性。\n",
    "\n",
    "例如对于上面词典中的\"love\"，其对应的标签为2，2的二进制表示为`010`，我们只需将编码线路中的`e_0`、`e_1`和`e_2`分别设为$0$、$\\pi$和$0$即可。下面来验证一下。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Label is:  2\n",
      "Binary label is:  010\n",
      "Parameters of encoder is: \n",
      " [0.      3.14159 0.     ]\n",
      "Encoder circuit is: \n",
      "       ┏━━━━━━━━━┓   \n",
      "q0: ──┨ RX(e_0) ┠───\n",
      "      ┗━━━━━━━━━┛   \n",
      "      ┏━━━━━━━━━┓   \n",
      "q1: ──┨ RX(e_1) ┠───\n",
      "      ┗━━━━━━━━━┛   \n",
      "      ┏━━━━━━━━━┓   \n",
      "q2: ──┨ RX(e_2) ┠───\n",
      "      ┗━━━━━━━━━┛   \n",
      "Encoder parameter names are: \n",
      " ['e_0', 'e_1', 'e_2']\n",
      "Amplitude of quantum state is: \n",
      " [0. 0. 1. 0. 0. 0. 0. 0.]\n",
      "Label in quantum state is:  2\n"
     ]
    }
   ],
   "source": [
    "from mindquantum.simulator import Simulator\n",
    "\n",
    "n_qubits = 3 # number of qubits of this quantum circuit\n",
    "label = 2 # label need to encode\n",
    "label_bin = bin(label)[-1: 1: -1].ljust(n_qubits, '0') # binary form of label\n",
    "label_array = np.array([int(i)*np.pi for i in label_bin]).astype(np.float32) # parameter value of encoder\n",
    "encoder = GenerateEncoderCircuit(n_qubits, prefix='e') # encoder circuit\n",
    "encoder_params_names = encoder.params_name # parameter names of encoder\n",
    "\n",
    "print(\"Label is: \", label)\n",
    "print(\"Binary label is: \", label_bin)\n",
    "print(\"Parameters of encoder is: \\n\", np.round(label_array, 5))\n",
    "print(\"Encoder circuit is: \\n\", encoder)\n",
    "print(\"Encoder parameter names are: \\n\", encoder_params_names)\n",
    "\n",
    "# quantum state evolution operator\n",
    "state = encoder.get_qs(pr=dict(zip(encoder_params_names, label_array)))\n",
    "amp = np.round(np.abs(state)**2, 3)\n",
    "\n",
    "print(\"Amplitude of quantum state is: \\n\", amp)\n",
    "print(\"Label in quantum state is: \", np.argmax(amp))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过上面的验证，我们发现，对于标签为2的数据，最后得到量子态的振幅最大的位置也是2，因此得到的量子态正是对输入标签的编码。我们将对数据编码生成参数数值的过程总结成如下函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def GenerateTrainData(sample, word_dict):\n",
    "    n_qubits = int(np.ceil(np.log2(1 + max(word_dict.values()))))\n",
    "    data_x = []\n",
    "    data_y = []\n",
    "    for around, center in sample:\n",
    "        data_x.append([])\n",
    "        for word in around:\n",
    "            label = word_dict[word]\n",
    "            label_bin = bin(label)[-1: 1: -1].ljust(n_qubits, '0')\n",
    "            label_array = [int(i)*np.pi for i in label_bin]\n",
    "            data_x[-1].extend(label_array)\n",
    "        data_y.append(word_dict[center])\n",
    "    return np.array(data_x).astype(np.float32), np.array(data_y).astype(np.int32)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([[0.       , 0.       , 0.       , 0.       , 3.1415927, 0.       ,\n",
       "         3.1415927, 0.       , 0.       , 0.       , 0.       , 3.1415927]],\n",
       "       dtype=float32),\n",
       " array([3], dtype=int32))"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "GenerateTrainData(sample, word_dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "根据上面的结果，我们将4个输入的词编码的信息合并为一个更长向量，便于后续神经网络调用。\n",
    "\n",
    "## Ansatz线路\n",
    "\n",
    "Ansatz线路的选择多种多样，我们选择如下的量子线路作为Ansatz线路，它的一个单元由一层 [RY](https://www.mindspore.cn/mindquantum/docs/zh-CN/master/core/gates/mindquantum.core.gates.RY.html) 门和一层 [CNOT](https://www.mindspore.cn/mindquantum/docs/zh-CN/master/core/gates/mindquantum.core.gates.CNOTGate.html) 门构成，对此单元重复$p$次构成整个Ansatz线路。\n",
    "\n",
    "![ansatz circuit](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/docs/mindquantum/docs/source_zh_cn/images/ansatz.png)\n",
    "\n",
    "定义如下函数生成Ansatz线路。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def GenerateAnsatzCircuit(n_qubits, layers, prefix=''):\n",
    "    if prefix and prefix[-1] != '_':\n",
    "        prefix += '_'\n",
    "    circ = Circuit()\n",
    "    for l in range(layers):\n",
    "        for i in range(n_qubits):\n",
    "            circ += RY(prefix + str(l) + '_' + str(i)).on(i)\n",
    "        for i in range(l % 2, n_qubits, 2):\n",
    "            if i < n_qubits and i + 1 < n_qubits:\n",
    "                circ += X.on(i + 1, i)\n",
    "    return circ.as_ansatz()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"416.8\" height=\"320.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><rect x=\"0\" y=\"0.0\" width=\"416.8\" height=\"320.0\" fill=\"#ffffff\" /><text x=\"20.0\" y=\"40.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q0: </text><text x=\"20.0\" y=\"100.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q1: </text><text x=\"20.0\" y=\"160.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q2: </text><text x=\"20.0\" y=\"220.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q3: </text><text x=\"20.0\" y=\"280.0\" font-size=\"16px\" dominant-baseline=\"middle\" text-anchor=\"start\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#252b3a\" >q4: </text><line x1=\"48.8\" x2=\"396.8\" y1=\"40.0\" y2=\"40.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"396.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"396.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"396.8\" y1=\"220.0\" y2=\"220.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><line x1=\"48.8\" x2=\"396.8\" y1=\"280.0\" y2=\"280.0\" stroke=\"#adb0b8\" stroke-width=\"1\" /><rect x=\"72.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"112.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_0_0 </text><rect x=\"72.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"112.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_0_1 </text><rect x=\"72.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"112.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_0_2 </text><rect x=\"72.8\" y=\"200.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"216.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"112.8\" y=\"232.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_0_3 </text><rect x=\"72.8\" y=\"260.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"112.8\" y=\"276.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"112.8\" y=\"292.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_0_4 </text><circle cx=\"192.8\" cy=\"40.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"40.0\" y2=\"100.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"172.8\" y=\"80.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"178.8\" x2=\"206.8\" y1=\"100.0\" y2=\"100.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"86.0\" y2=\"114.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"192.8\" cy=\"160.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"160.0\" y2=\"220.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"172.8\" y=\"200.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"178.8\" x2=\"206.8\" y1=\"220.0\" y2=\"220.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"192.8\" x2=\"192.8\" y1=\"206.0\" y2=\"234.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><rect x=\"232.8\" y=\"20.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"272.8\" y=\"36.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"272.8\" y=\"52.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_1_0 </text><rect x=\"232.8\" y=\"80.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"272.8\" y=\"96.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"272.8\" y=\"112.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_1_1 </text><rect x=\"232.8\" y=\"140.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"272.8\" y=\"156.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"272.8\" y=\"172.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_1_2 </text><rect x=\"232.8\" y=\"200.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"272.8\" y=\"216.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"272.8\" y=\"232.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_1_3 </text><rect x=\"172.8\" y=\"260.0\" width=\"80.0\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#fac209\" fill-opacity=\"1\" /><text x=\"212.8\" y=\"276.0\" font-size=\"20px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >RY </text><text x=\"212.8\" y=\"292.0\" font-size=\"14.0px\" dominant-baseline=\"middle\" text-anchor=\"middle\" font-family=\"Arial\" font-weight=\"normal\" fill=\"#ffffff\" >a_1_4 </text><circle cx=\"352.8\" cy=\"100.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"352.8\" x2=\"352.8\" y1=\"100.0\" y2=\"160.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"332.8\" y=\"140.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"338.8\" x2=\"366.8\" y1=\"160.0\" y2=\"160.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"352.8\" x2=\"352.8\" y1=\"146.0\" y2=\"174.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><circle cx=\"352.8\" cy=\"220.0\" r=\"4\" fill=\"#16acff\" /><line x1=\"352.8\" x2=\"352.8\" y1=\"220.0\" y2=\"280.0\" stroke=\"#16acff\" stroke-width=\"3\" /><rect x=\"332.8\" y=\"260.0\" width=\"40\" height=\"40\" rx=\"4\" ry=\"4\" stroke=\"#ffffff\" stroke-width=\"0\" fill=\"#16acff\" fill-opacity=\"1\" /><line x1=\"338.8\" x2=\"366.8\" y1=\"280.0\" y2=\"280.0\" stroke=\"#ffffff\" stroke-width=\"4\" /><line x1=\"352.8\" x2=\"352.8\" y1=\"266.0\" y2=\"294.0\" stroke=\"#ffffff\" stroke-width=\"4\" /></svg>"
      ],
      "text/plain": [
       "<mindquantum.io.display.circuit_svg_drawer.SVGCircuit at 0x7f91b3188670>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "GenerateAnsatzCircuit(5, 2, 'a').svg()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 测量\n",
    "\n",
    "我们把对不同比特位上的测量结果作为降维后的数据。具体过程与比特编码类似，例如当我们想将词向量降维为五维向量时，对于第三维的数据可以如下产生：\n",
    "\n",
    "- 3对应的二进制为`00011`。\n",
    "- 测量量子线路末态对$Z_0Z_1$哈密顿量的期望值。\n",
    "\n",
    "下面函数将给出产生各个维度上数据所需的哈密顿量（hams），其中`n_qubits`表示线路的比特数，`dims`表示词嵌入的维度："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def GenerateEmbeddingHamiltonian(dims, n_qubits):\n",
    "    hams = []\n",
    "    for i in range(dims):\n",
    "        s = ''\n",
    "        for j, k in enumerate(bin(i + 1)[-1:1:-1]):\n",
    "            if k == '1':\n",
    "                s = s + 'Z' + str(j) + ' '\n",
    "        hams.append(Hamiltonian(QubitOperator(s)))\n",
    "    return hams"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1 [Z0], 1 [Z1], 1 [Z0 Z1], 1 [Z2], 1 [Z0 Z2]]"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "GenerateEmbeddingHamiltonian(5, 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 量子版词向量嵌入层\n",
    "\n",
    "量子版词向量嵌入层结合前面的编码量子线路和待训练量子线路，以及测量哈密顿量，将`num_embedding`个词嵌入为`embedding_dim`维的词向量。这里我们还在量子线路的最开始加上了Hadamard门，将初态制备为均匀叠加态，用以提高量子神经网络的表达能力。\n",
    "\n",
    "下面，我们定义量子嵌入层，它将返回一个量子线路模拟算子。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def QEmbedding(num_embedding, embedding_dim, window, layers, n_threads):\n",
    "    n_qubits = int(np.ceil(np.log2(num_embedding)))\n",
    "    hams = GenerateEmbeddingHamiltonian(embedding_dim, n_qubits)\n",
    "    circ = Circuit()\n",
    "    circ = UN(H, n_qubits)\n",
    "    encoder_param_name = []\n",
    "    ansatz_param_name = []\n",
    "    for w in range(2 * window):\n",
    "        encoder = GenerateEncoderCircuit(n_qubits, 'Encoder_' + str(w))\n",
    "        ansatz = GenerateAnsatzCircuit(n_qubits, layers, 'Ansatz_' + str(w))\n",
    "        encoder.no_grad()\n",
    "        circ += encoder\n",
    "        circ += ansatz\n",
    "        encoder_param_name.extend(encoder.params_name)\n",
    "        ansatz_param_name.extend(ansatz.params_name)\n",
    "    grad_ops = Simulator('mqvector', circ.n_qubits).get_expectation_with_grad(hams,\n",
    "                                                                              circ,\n",
    "                                                                              parallel_worker=n_threads)\n",
    "    return MQLayer(grad_ops)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "整个训练模型跟经典网络类似，由一个嵌入层和两个全连通层构成，然而此处的嵌入层是由量子神经网络构成。下面定义量子神经网络CBOW。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "class CBOW(nn.Cell):\n",
    "    def __init__(self, num_embedding, embedding_dim, window, layers, n_threads,\n",
    "                 hidden_dim):\n",
    "        super(CBOW, self).__init__()\n",
    "        self.embedding = QEmbedding(num_embedding, embedding_dim, window,\n",
    "                                    layers, n_threads)\n",
    "        self.dense1 = nn.Dense(embedding_dim, hidden_dim)\n",
    "        self.dense2 = nn.Dense(hidden_dim, num_embedding)\n",
    "        self.relu = ops.ReLU()\n",
    "\n",
    "    def construct(self, x):\n",
    "        embed = self.embedding(x)\n",
    "        out = self.dense1(embed)\n",
    "        out = self.relu(out)\n",
    "        out = self.dense2(out)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "下面我们对一个稍长的句子来进行训练。首先定义`LossMonitorWithCollection`用于监督收敛过程，并搜集收敛过程的损失。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "class LossMonitorWithCollection(ms.train.callback.LossMonitor):\n",
    "    def __init__(self, per_print_times=1):\n",
    "        super(LossMonitorWithCollection, self).__init__(per_print_times)\n",
    "        self.loss = []\n",
    "\n",
    "    def on_train_begin(self, run_context):\n",
    "        self.begin_time = time.time()\n",
    "\n",
    "    def on_train_end(self, run_context):\n",
    "        self.end_time = time.time()\n",
    "        print('Total time used: {}'.format(self.end_time - self.begin_time))\n",
    "\n",
    "    def on_train_epoch_begin(self, run_context):\n",
    "        self.epoch_begin_time = time.time()\n",
    "\n",
    "    def on_train_epoch_end(self, run_context):\n",
    "        cb_params = run_context.original_args()\n",
    "        self.epoch_end_time = time.time()\n",
    "        if self._per_print_times != 0 and cb_params.cur_step_num % self._per_print_times == 0:\n",
    "            print('')\n",
    "\n",
    "    def on_train_step_end(self, run_context):\n",
    "        cb_params = run_context.original_args()\n",
    "        loss = cb_params.net_outputs\n",
    "\n",
    "        if isinstance(loss, (tuple, list)):\n",
    "            if isinstance(loss[0], ms.Tensor) and isinstance(loss[0].asnumpy(), np.ndarray):\n",
    "                loss = loss[0]\n",
    "\n",
    "        if isinstance(loss, ms.Tensor) and isinstance(loss.asnumpy(), np.ndarray):\n",
    "            loss = np.mean(loss.asnumpy())\n",
    "\n",
    "        cur_step_in_epoch = (cb_params.cur_step_num - 1) % cb_params.batch_num + 1\n",
    "\n",
    "        if isinstance(loss, float) and (np.isnan(loss) or np.isinf(loss)):\n",
    "            raise ValueError(\"epoch: {} step: {}. Invalid loss, terminating training.\".format(\n",
    "                cb_params.cur_epoch_num, cur_step_in_epoch))\n",
    "        self.loss.append(loss)\n",
    "        if self._per_print_times != 0 and cb_params.cur_step_num % self._per_print_times == 0:\n",
    "            print(\"\\repoch: %+3s step: %+3s time: %5.5s, loss is %5.5s\" % (cb_params.cur_epoch_num, cur_step_in_epoch, time.time() - self.epoch_begin_time, loss), flush=True, end='')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来，利用量子版本的`CBOW`来对一个长句进行词嵌入。运行之前请在终端运行`export OMP_NUM_THREADS=4`，将量子模拟器的线程数设置为4个，当所需模拟的量子系统比特数较多时，可设置更多的线程数来提高模拟效率。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch:  25 step:  20 time: 0.221, loss is 0.103\n",
      "epoch:  50 step:  20 time: 0.213, loss is 0.049\n",
      "epoch:  75 step:  20 time: 0.212, loss is 0.031\n",
      "epoch: 100 step:  20 time: 0.213, loss is 0.023\n",
      "epoch: 125 step:  20 time: 0.214, loss is 0.018\n",
      "epoch: 150 step:  20 time: 0.212, loss is 0.020\n",
      "epoch: 175 step:  20 time: 0.212, loss is 0.022\n",
      "epoch: 200 step:  20 time: 0.220, loss is 0.022\n",
      "epoch: 225 step:  20 time: 0.213, loss is 0.025\n",
      "epoch: 250 step:  20 time: 0.212, loss is 0.022\n",
      "epoch: 275 step:  20 time: 0.212, loss is 0.022\n",
      "epoch: 300 step:  20 time: 0.214, loss is 0.019\n",
      "epoch: 325 step:  20 time: 0.213, loss is 0.021\n",
      "epoch: 350 step:  20 time: 0.209, loss is 0.019\n",
      "Total time used: 76.30937623977661\n"
     ]
    }
   ],
   "source": [
    "import mindspore as ms\n",
    "ms.set_context(mode=ms.PYNATIVE_MODE, device_target=\"CPU\")\n",
    "corpus = \"\"\"We are about to study the idea of a computational process.\n",
    "Computational processes are abstract beings that inhabit computers.\n",
    "As they evolve, processes manipulate other abstract things called data.\n",
    "The evolution of a process is directed by a pattern of rules\n",
    "called a program. People create programs to direct processes. In effect,\n",
    "we conjure the spirits of the computer with our spells.\"\"\"\n",
    "\n",
    "ms.set_seed(42)\n",
    "window_size = 2\n",
    "embedding_dim = 10\n",
    "hidden_dim = 128\n",
    "word_dict, sample = GenerateWordDictAndSample(corpus, window=window_size)\n",
    "train_x, train_y = GenerateTrainData(sample, word_dict)\n",
    "\n",
    "train_loader = ds.NumpySlicesDataset({\n",
    "    \"around\": train_x,\n",
    "    \"center\": train_y\n",
    "}, shuffle=False).batch(3)\n",
    "net = CBOW(len(word_dict), embedding_dim, window_size, 3, 4, hidden_dim)\n",
    "net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n",
    "net_opt = nn.Momentum(net.trainable_params(), 0.01, 0.9)\n",
    "loss_monitor = LossMonitorWithCollection(500)\n",
    "model = ms.Model(net, net_loss, net_opt)\n",
    "model.train(350, train_loader, callbacks=[loss_monitor], dataset_sink_mode=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "打印收敛过程中的损失函数值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot(loss_monitor.loss, '.')\n",
    "plt.xlabel('Steps')\n",
    "plt.ylabel('Loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "通过如下方法打印量子嵌入层的量子线路中的参数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 8.28509405e-02, -3.26783717e-01, -1.20854974e-01,  5.79170465e-01,\n",
       "       -4.23381245e-03,  3.29294635e-05,  2.43815452e-01,  8.71518493e-01,\n",
       "       -1.44472703e-01, -7.79354339e-03,  2.70770327e-03,  1.65945366e-02,\n",
       "        2.40263134e-01, -2.47914240e-01, -6.54938519e-01,  1.20716286e-03,\n",
       "       -9.82751808e-05, -7.48598017e-03,  4.76213545e-01,  9.89681557e-02,\n",
       "        8.84049339e-04, -1.90813065e-01,  5.48663782e-03,  2.60578927e-05,\n",
       "        2.83720374e-01, -3.61616552e-01,  2.54671965e-02, -1.55609414e-01,\n",
       "       -5.39148413e-03, -1.15224821e-02,  2.88882911e-01, -5.79479873e-01,\n",
       "       -2.51826912e-01, -1.78641319e-01, -5.69021329e-04, -3.33189149e-03,\n",
       "        4.28463630e-02,  2.38046542e-01,  1.34105897e+00, -9.38638091e-01,\n",
       "        1.56452111e-03,  1.36013608e-04,  7.44504556e-02, -3.08786072e-02,\n",
       "       -1.25253260e-01,  4.26549762e-01, -2.84173930e-05, -1.36818904e-02,\n",
       "        7.19586536e-02, -2.98673570e-01, -1.77007183e-01,  4.15215105e-01,\n",
       "       -7.02699134e-03, -3.31260450e-03,  2.77717616e-02,  2.76488215e-01,\n",
       "       -2.78314471e-01,  1.96258754e-01, -1.70984527e-03, -2.29887012e-03,\n",
       "        7.09533542e-02, -1.89099953e-01, -1.30285263e-01, -1.50424615e-01,\n",
       "       -5.65047842e-03, -7.44100334e-03,  5.27282506e-02, -6.42003343e-02,\n",
       "        1.25932191e-02, -1.31718621e-01,  1.74699686e-02, -1.28326667e-02],\n",
       "      dtype=float32)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net.embedding.weight.asnumpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 经典版词向量嵌入层\n",
    "\n",
    "这里我们利用经典的词向量嵌入层来搭建一个经典的CBOW神经网络，并与量子版本进行对比。\n",
    "\n",
    "首先，搭建经典的CBOW神经网络，其中的参数跟量子版本的类似。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "class CBOWClassical(nn.Cell):\n",
    "    def __init__(self, num_embedding, embedding_dim, window, hidden_dim):\n",
    "        super(CBOWClassical, self).__init__()\n",
    "        self.dim = 2 * window * embedding_dim\n",
    "        self.embedding = nn.Embedding(num_embedding, embedding_dim, True)\n",
    "        self.dense1 = nn.Dense(self.dim, hidden_dim)\n",
    "        self.dense2 = nn.Dense(hidden_dim, num_embedding)\n",
    "        self.relu = ops.ReLU()\n",
    "        self.reshape = ops.Reshape()\n",
    "\n",
    "    def construct(self, x):\n",
    "        embed = self.embedding(x)\n",
    "        embed = self.reshape(embed, (-1, self.dim))\n",
    "        out = self.dense1(embed)\n",
    "        out = self.relu(out)\n",
    "        out = self.dense2(out)\n",
    "        return out"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "生成适用于经典CBOW神经网络的数据集。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train_x shape:  (58, 4)\n",
      "train_y shape:  (58,)\n"
     ]
    }
   ],
   "source": [
    "train_x = []\n",
    "train_y = []\n",
    "for i in sample:\n",
    "    around, center = i\n",
    "    train_y.append(word_dict[center])\n",
    "    train_x.append([])\n",
    "    for j in around:\n",
    "        train_x[-1].append(word_dict[j])\n",
    "train_x = np.array(train_x).astype(np.int32)\n",
    "train_y = np.array(train_y).astype(np.int32)\n",
    "print(\"train_x shape: \", train_x.shape)\n",
    "print(\"train_y shape: \", train_y.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们对经典CBOW网络进行训练。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "epoch:  25 step:  20 time: 0.022, loss is 0.627\n",
      "epoch:  50 step:  20 time: 0.020, loss is 0.011\n",
      "epoch:  75 step:  20 time: 0.020, loss is 0.003\n",
      "epoch: 100 step:  20 time: 0.020, loss is 0.002\n",
      "epoch: 125 step:  20 time: 0.020, loss is 0.001\n",
      "epoch: 150 step:  20 time: 0.023, loss is 0.001\n",
      "epoch: 175 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 200 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 225 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 250 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 275 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 300 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 325 step:  20 time: 0.020, loss is 0.000\n",
      "epoch: 350 step:  20 time: 0.020, loss is 0.000\n",
      "Total time used: 7.7057013511657715\n"
     ]
    }
   ],
   "source": [
    "ms.set_context(mode=ms.GRAPH_MODE, device_target=\"CPU\")\n",
    "\n",
    "train_loader = ds.NumpySlicesDataset({\n",
    "    \"around\": train_x,\n",
    "    \"center\": train_y\n",
    "}, shuffle=False).batch(3)\n",
    "net = CBOWClassical(len(word_dict), embedding_dim, window_size, hidden_dim)\n",
    "net_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n",
    "net_opt = nn.Momentum(net.trainable_params(), 0.01, 0.9)\n",
    "loss_monitor = LossMonitorWithCollection(500)\n",
    "model = ms.Model(net, net_loss, net_opt)\n",
    "model.train(350, train_loader, callbacks=[loss_monitor], dataset_sink_mode=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "打印收敛过程中的损失函数值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "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lJjriI3giIjI17RpRqWiogKSJGHw4MEAgH379mH16tW44YYb8Mgjj7TrDXYFjstBkQa9y5wSAWDNvnLcntDfaSamJUyuJSIiX9OmGZV58+Zh+/btAIDKykrccccd2LdvH/74xz/iz3/+c7veYFcRadDblSRHGvQYFxuqOvbvW09h1tICzEoZZDcTMyfV/fevzh7FZR8iIvIpbWr4Fhoaij179mDEiBF44403sHbtWnz99df417/+hcceewynT6vv/tvefK3hW2sYTWa3zdwAa/Cx/ok0NDRZ7GZiHGdm1BrHEREReUuHN3y7cuUKgoKCAABfffUV7r77bgBAQkICjEbnvWeo9Uqr690GKYA156ShyYK0+H7Ka46Juo7fExER+ZI2Lf3ceOONePvtt7F79258+eWXmD59OgDg3Llz6NevXwtnkyfiwnrCg95wyD9VxT4pRETkt9oUqCxevBjLly/HbbfdhnvvvRfJyckAgM8++wzjxo1r1xvsqiINeiy4Ja7FcUu2l2Deir2YmLsNa/eXd8KdERERdZ42b0rY3NyMuro6hIZeS/gsKytDcHAw+vfv32436I4/56gAnm1iaEvOWalvakZcWE8u+RARkSa15u93m2ZUzGYzGhsblSDlzJkzeP3113HixIlOC1L8kVq7/IcmxSn7A+kAt8tBzUJg5tICzrAQEZHfaFMy7T333IPZs2fjscceQ21tLcaPH4/u3bujuroaf/vb3/D444+39336veW7SpCbVwzxU7v7WSmDsKHwrNI+/5H0OMyfGIddJ6vw3PpjaHYxESa/bBFA9roidqIlIiKf1qYZlUOHDuGWW24BAHzyyScYMGAAzpw5g3/84x9444032vUGu4LlO0uQs6nYLshYd+isXfv8d3eXAbA2h8vPmowPF9yM7DsTlD4paj9IC4BV+WUdfPdEREQdp00zKg0NDejduzcA4F//+hdmz54NnU6Hm2++GWfOnGnXG/R3RpMZuXmu9+yRye3v5XJjuUHc3ckDUVbdgIamK3jo/YNO563MP435k2I5q0JERD6pTTMqQ4cOxcaNG1FRUYEtW7bgZz/7GQDg/PnzrUpqzcnJwdixY9G7d2/0798fM2fOxIkTJ9pySz7Lk34pgOv295EGPcov1GPBP5yDFMA6O8P9fYiIyFe1KVB54YUX8Pvf/x6xsbEYN24c0tLS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XnH69GmxZcsWcerUKWWMP/9beP78ebuf/5dffikAiO3btwshfON3gIGKg3HjxonMzEzl++bmZjFw4ECRk5Pjxbu6fo6BisViEREREeKvf/2r8lptba0ICgoSH374oRBCiO+++04AEPv371fG5OXlCUmSxNmzZ4UQQixdulSEhoaKxsZGZcyiRYvEiBEjOviJWu/8+fMCgNi5c6cQwvq83bt3Fx9//LEy5vjx4wKA+Oabb4QQ1mBPp9OJyspKZcyyZctESEiI8szPPvusuPHGG+3ea+7cuWLatGkd/UhtEhoaKlauXNmlnv/ixYti2LBh4ssvvxS33nqrEqj4+2fw4osviuTkZNVj/v7sskWLFolJkya5PN7V/i186qmnRHx8vLBYLD7zO8ClHxtNTU04ePAgpk6dqrym0+kwdepUfPPNN168s/ZXWlqKyspKu2c1GAwYP3688qzffPMN+vTpg5tuukkZM3XqVOh0Ouzdu1cZk56ejsDAQGXMtGnTcOLECdTU1HTS03jGZDIBAPr27QsAOHjwIK5cuWL3GSQkJCA6OtruM0hMTMSAAQOUMdOmTUNdXR2+/fZbZYztNeQxWvudaW5uxpo1a1BfX4+0tLQu9fyZmZmYMWOG0312hc/g+++/x8CBAzFkyBDcd999KC8vB9A1nh0APvvsM9x000345S9/if79+yMlJQUrVqxQjnelfwubmprwz3/+E7/5zW8gSZLP/A4wULFRXV2N5uZmux8IAAwYMACVlZVeuquOIT+Pu2etrKxE//797Y5369YNffv2tRujdg3b99ACi8WCp59+GhMnTsSoUaMAWO8vMDAQffr0sRvr+Bm09HyuxtTV1cFsNnfE47RKUVERevXqhaCgIDz22GPYsGEDbrjhhi7z/GvWrMGhQ4eQk5PjdMzfP4Px48fjvffew+bNm7Fs2TKUlpbilltuwcWLF/3+2WWnT5/GsmXLMGzYMGzZsgWPP/44nnzySbz//vsAuta/hRs3bkRtbS0efPBBAL7z++/TuycTeSozMxPHjh1Dfn6+t2+l040YMQKHDx+GyWTCJ598ggceeAA7d+709m11ioqKCjz11FP48ssv0aNHD2/fTqfLyMhQ/j8pKQnjx49HTEwMPvroI+j1ei/eWeexWCy46aab8OqrrwIAUlJScOzYMbz99tt44IEHvHx3nevdd99F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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot(loss_monitor.loss, '.')\n",
    "plt.xlabel('Steps')\n",
    "plt.ylabel('Loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "由上可知，通过量子模拟得到的量子版词嵌入模型也能很好的完成嵌入任务。当数据集大到经典计算机算力难以承受时，量子计算机将能够轻松处理这类问题。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "<table border=\"1\">\n",
       "  <tr>\n",
       "    <th>Software</th>\n",
       "    <th>Version</th>\n",
       "  </tr>\n",
       "<tr><td>mindquantum</td><td>0.9.11</td></tr>\n",
       "<tr><td>scipy</td><td>1.13.1</td></tr>\n",
       "<tr><td>numpy</td><td>1.26.4</td></tr>\n",
       "<tr>\n",
       "    <th>System</th>\n",
       "    <th>Info</th>\n",
       "</tr>\n",
       "<tr><td>Python</td><td>3.9.19</td></tr><tr><td>OS</td><td>Linux x86_64</td></tr><tr><td>Memory</td><td>19.01 GB</td></tr><tr><td>CPU Max Thread</td><td>9</td></tr><tr><td>Date</td><td>Fri Aug 23 07:01:18 2024</td></tr>\n",
       "</table>\n"
      ],
      "text/plain": [
       "<mindquantum.utils.show_info.InfoTable at 0x7f916cc50bb0>"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindquantum.utils.show_info import InfoTable\n",
    "\n",
    "InfoTable('mindquantum', 'scipy', 'numpy')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 参考文献\n",
    "\n",
    "[1] Tomas Mikolov, Kai Chen, Greg Corrado, Jeffrey Dean. [Efficient Estimation of Word Representations in\n",
    "Vector Space](https://arxiv.org/pdf/1301.3781.pdf)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
